package com.zoe.onelink.core.autoconfigure;

import brave.Tracer;
import com.zoe.onelink.common.constant.OnelinkConstant;
import com.zoe.onelink.core.exception.handler.OnelinkBasicErrorController;
import com.zoe.onelink.core.web.filter.OnelinkRequestFilter;
import com.zoe.onelink.core.web.filter.RequestBodyWrapperFilter;
import com.zoe.onelink.core.web.response.ResultWrapperResponseBodyAdvice;
import com.zoe.onelink.core.web.response.trace.TraceIdProvider;
import com.zoe.onelink.core.web.response.trace.ZipkinTraceIdProvider;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import javax.servlet.Filter;
import java.util.stream.Collectors;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2021</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2021-12-08
 */
@Configuration(proxyBeanMethods = false)
@Import({ResultWrapperResponseBodyAdvice.class})
@AutoConfigureBefore(ErrorMvcAutoConfiguration.class)
public class OnelinkWebAutoConfiguration {


    @Bean(OnelinkConstant.CACHED_REQUEST_BODY_WRAPPER)
    @ConditionalOnMissingBean(name = OnelinkConstant.CACHED_REQUEST_BODY_WRAPPER)
    public FilterRegistrationBean<Filter> filterRegistrationBean() {
        RequestBodyWrapperFilter requestBodyWrapperFilter = new RequestBodyWrapperFilter();
        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>(requestBodyWrapperFilter);
        // 过滤所有路径
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }


    @Bean
    public FilterRegistrationBean<Filter> onelinkRequestFilter() {
        FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>(new OnelinkRequestFilter());
        // 过滤所有路径
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(Tracer.class)
    public static class OnelinkCoreTraceAutoConfiguration {

        @Bean
        @ConditionalOnMissingBean(TraceIdProvider.class)
        public TraceIdProvider zipkinTraceIdProvider(ObjectProvider<Tracer> tracer) {
            return new ZipkinTraceIdProvider(tracer.getIfAvailable());
        }

    }

    @Bean
    @ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
    public BasicErrorController basicErrorController(ErrorAttributes errorAttributes,
                                                     ObjectProvider<ErrorViewResolver> errorViewResolvers,
                                                     ServerProperties serverProperties) {
        return new OnelinkBasicErrorController(errorAttributes, serverProperties.getError(),
                errorViewResolvers.orderedStream().collect(Collectors.toList()));
    }

}
